﻿using System;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Blackbird.Core.Editable;
using Blackbird.Core.Editable.Frames;
using Blackbird.Core.Editable.Map;
using Blackbird.Core.Editable.Sprites;
using Blackbird.Studio.Context;
using Blackbird.Studio.ViewModel.EntityViewModels;

namespace Blackbird.Studio.ViewModel {
    public class DesignerViewModel : MarshalByRefObject {

        public static DesignerViewModel Instance { get; private set; }
        static DesignerViewModel()
        {
            Instance = new DesignerViewModel {
                MainWindowViewModel = new MainWindowViewModel(),
                EditableModuleViewModel = EntityModelContext.CreateViewModel<EditableModuleViewModel, EditableModule>(),
                EditableLayeredMapViewModel = EntityModelContext.CreateViewModel<EditableLayeredMapViewModel, EditableLayeredMap>()
            };

            for(int sprite = 0; sprite < 3; sprite++)
            {
                var spriteViewModel = EntityModelContext.CreateViewModel<EditableMultispriteViewModel, EditableMultisprite>();
                spriteViewModel.Model.Name = string.Format("Sprite {0}", sprite + 1);
                for(int framesetList = 0; framesetList < 3; framesetList ++)
                {
                    var framesetListViewModel =
                        EntityModelContext.CreateViewModel<EditableFramesetListViewModel, EditableFramesetList>();
                    int framesetListIndex = (framesetList + (sprite * 3)) +1;
                    framesetListViewModel.Model.Name = string.Format("FramesetList {0}", framesetListIndex);
                    for (int frameset = 0; frameset < 3; frameset++)
                    {
                        var framesetViewModel =
                            EntityModelContext.CreateViewModel<EditableFramesetViewModel, EditableFrameset>();
                        int framesetIndex = ((frameset) + (framesetList * 3) + (sprite * 9)) +1;
                        framesetViewModel.Model.Name = string.Format("Frameset {0}", framesetIndex);
                        for (int frame = 0; frame < 5; frame++)
                        {
                            var frameViewModel = EntityModelContext.CreateViewModel<EditableFrameViewModel, EditableFrame>();
                            int frameIndex = (frame + (frameset*3) + (framesetList*9) + (sprite*27)) + 1;
                            frameViewModel.Model.Name = string.Format("Image {0}", frameIndex);
                            frameViewModel.Model.BitmapSource = GenerateSampleBitmap(frameViewModel.Model.Name);
                            
                            framesetViewModel.Add(frameViewModel);
                        }

                        framesetListViewModel.Add(framesetViewModel);
                    }
                    spriteViewModel.Add(framesetListViewModel);
                }                
                Instance.EditableModuleViewModel.Sprites.Add(spriteViewModel);
            }
            
            Instance.EditableMultispriteViewModel = Instance.EditableModuleViewModel.Sprites.Last();
            Instance.EditableFramesetListViewModel = Instance.EditableMultispriteViewModel.Last();
            Instance.EditableFramesetViewModel = Instance.EditableFramesetListViewModel.Last();
            Instance.EditableFrameViewModel = Instance.EditableFramesetViewModel.Last();

            Instance.MainWindowViewModel.ActiveModule = Instance.EditableModuleViewModel;
            //Instance.EditableModuleViewModel.SelectedSprite = Instance.EditableMultispriteViewModel;
            Instance.EditableMultispriteViewModel.SelectedItem = Instance.EditableFramesetListViewModel;
            Instance.EditableFramesetListViewModel.SelectedItem = Instance.EditableFramesetViewModel;
            Instance.EditableFramesetViewModel.SelectedItem = Instance.EditableFrameViewModel;
            for (int map = 0; map < 1; map++)
            {
                var mapVm = EntityModelContext.CreateViewModel<EditableLayeredMapViewModel, EditableLayeredMap>();
                for (int mapLayer = 0; mapLayer < 2; mapLayer++)
                {
                    var mapLayerVm = EntityModelContext.CreateViewModel<EditableMapLayerViewModel, EditableMapLayer>();
                    mapLayerVm.Model.LayerIndex = mapLayer;
                    mapLayerVm.Model.Width = 5;
                    mapLayerVm.Model.Height = 5;
                    for (int nodeX = 0; nodeX < 5; nodeX++)
                    {
                        for (int nodeY = 0; nodeY < 5; nodeY++)
                        {
                            var staticMapNode = new EditableStaticMapNode
                                                    {
                                                        Frame = new EditableFrame
                                                                    {
                                                                        BitmapSource =
                                                                            GenerateSampleBitmap(
                                                                                string.Format("Tile {0}x{1}", nodeX,
                                                                                              nodeY))
                                                                    }
                                                    };

                            mapLayerVm.Model[nodeX, nodeY] = staticMapNode;

                        }
                    }
                    mapVm.Add(mapLayerVm);
                }
                Instance.EditableModuleViewModel.Maps.Add(mapVm);
            }

            Instance.EditableLayeredMapViewModel = Instance.EditableModuleViewModel.Maps.Last();
            Instance.EditableMapLayerViewModel = Instance.EditableLayeredMapViewModel.Last();
            Instance.EditableModuleViewModel.SelectedMap = Instance.EditableLayeredMapViewModel;
            Instance.EditableLayeredMapViewModel.SelectedItem = Instance.EditableMapLayerViewModel;
        }

        public static BitmapSource GenerateSampleBitmap(string imageText)
        {
            var visual = new DrawingVisual();
            using(var context = visual.RenderOpen())
            {
                var text = GenerateText(imageText);
                RenderText(context, text, GetTextOrigin(text));
            }
            var targetBitmap = new RenderTargetBitmap(256, 256, 96.0, 96.0, PixelFormats.Pbgra32);
            targetBitmap.Render(visual);
            return targetBitmap;
        }

        private static FormattedText GenerateText(string imageText) {
            Typeface typeface = GenerateTypeface();
            return new FormattedText(imageText, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface,
                                         20, Brushes.Cornsilk) { MaxTextWidth = 246, MaxTextHeight = 246 };
        }

        private static Point GetTextOrigin(FormattedText text) {
            return new Point {
                X = (128.0) - (text.Width / 2.0),
                Y = (128.0) - (text.Height / 2.0)
            };
        }

        private static void RenderText(DrawingContext context, FormattedText text, Point origin) {
            context.DrawRectangle(Brushes.DarkBlue, new Pen(Brushes.Cornsilk, 1.0), new Rect(5, 5, 250, 250));
            context.DrawText(text, origin);
        }

        private static Typeface GenerateTypeface() {
            return new Typeface(new FontFamily("Consolas"), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);
        }
        
        public override object InitializeLifetimeService() {
            return null;
        }

        public EditableFramesetListViewModel EditableFramesetListViewModel { get; private set; }
        public EditableFramesetViewModel EditableFramesetViewModel { get; private set; }
        public EditableFrameViewModel EditableFrameViewModel { get; private set; }
        public EditableLayeredMapViewModel EditableLayeredMapViewModel { get; private set; }
        public EditableMapLayerViewModel EditableMapLayerViewModel { get; private set; }
        public EditableModuleViewModel EditableModuleViewModel { get; private set; }
        public EditableMultispriteViewModel EditableMultispriteViewModel { get; private set; }
        public MainWindowViewModel MainWindowViewModel { get; private set; }
        
    }
}
